'use client';

import clsx from 'clsx';
import Image from 'next/image';
import toast from 'react-hot-toast';
import React, { useCallback, useDeferredValue, useImperativeHandle, useMemo } from 'react';
import {
  ArrowDownTrayIcon,
  ChevronUpDownIcon,
  CloudArrowUpIcon,
  EllipsisVerticalIcon,
  PencilSquareIcon,
  ShareIcon,
  TrashIcon,
} from '@heroicons/react/24/outline';
import { FolderFilled } from '@ant-design/icons';
import { useRouter, useSearchParams } from 'next/navigation';
import { copyToClipboard } from 'src/utils';
import { Dropdown } from 'src/components/Dropdown';
import { ExplorerItem } from 'src/hooks/useExplorerInfiniteScroll';
import { IconRename } from 'src/components/Icons';
import { ImageView } from 'src/components/ImageView';
import { Table, TableProps } from 'src/components/Table';
import { IntersectionObserver } from 'src/components/IntersectionObserver';
import { GridView } from './GridView';

export interface GalleryListProps {
  ref?: React.Ref<HTMLDivElement>;
  className?: string;
  /**
   * 显示模式
   * @default 'list'
   * @description 'grid' - 网格模式，'list' - 列表模式
   */
  mode?: 'grid' | 'list';
  /**
   * 是否为搜索模式
   */
  isSearchMode?: boolean;
  dataSource?: ExplorerItem[];
  loading?: boolean;
  /**
   * 是否在底部显示加载更多的loading
   */
  loadingMore?: boolean;
  /**
   * 是否显示没有更多数据
   */
  noMore?: boolean;
  selectedKeys: string[];
  onSelect: (selectedKeys: string[]) => void;
}

function GalleryListNoMemoized(props: GalleryListProps) {
  const {
    ref,
    className,
    mode = 'list',
    isSearchMode,
    dataSource,
    loading,
    loadingMore,
    noMore,
    selectedKeys,
    onSelect,
  } = props;
  const deferredMode = useDeferredValue(mode);

  // Hooks
  const router = useRouter();
  const searchParams = useSearchParams();

  // Refs
  const containerRef = React.useRef<HTMLDivElement>(null);
  useImperativeHandle(ref, () => containerRef.current!);

  // Handlers
  const calculateFileSize = useCallback((value: number) => {
    if (!value) return '-';
    let fileSize = value / 1024; // KB
    if (fileSize > 1024) {
      fileSize = fileSize / 1024; // MB
      return `${fileSize.toFixed(2)} MB`;
    }
    return `${fileSize.toFixed(2)} KB`;
  }, []);

  const handleItemClick = useCallback(
    (item: ExplorerItem) => {
      if (item.type === 'folder') {
        const query = new URLSearchParams(searchParams);
        query.set('folderId', item.id);
        router.push(`/workbench/gallery?${query.toString()}`);
      }
      if (item.type === 'image') {
        router.push(`/console/${item.id}`);
      }
    },
    [router, searchParams]
  );

  const rowProps = useCallback<NonNullable<TableProps<ExplorerItem>['rowProps']>>(
    (item) => {
      let title = '';
      let fileSizeStr = '-';
      if (item.type === 'folder') {
        // 文件夹
        title = `文件夹：${item.name}\n`;
        title += `描述：${item.description || '-'}\n`;
        title += `创建时间：${item.createdAt}`;
      } else if (item.type === 'image') {
        // 图片
        if (item.fileSize) {
          fileSizeStr = calculateFileSize(item.fileSize);
        }
        title = `图片：${item.name}\n`;
        title += `尺寸：${item.metadata?.width}*${item.metadata?.height}\n`;
        title += `格式：${item.metadata?.mimeType}\n`;
        title += `大小：${fileSizeStr}`;
      }
      return {
        title,
        className: clsx(
          'hover:cursor-pointer active:bg-base-200',
          selectedKeys.includes(item.id) &&
            'bg-purple-100 dark:bg-purple-800/50 hover:bg-purple-200 dark:hover:bg-purple-700/50'
        ),
        onClick() {
          handleItemClick(item);
        },
      };
    },
    [selectedKeys, calculateFileSize, handleItemClick]
  );

  // Memoized
  const rowSelectionColumn = useMemo<TableProps['rowSelectionColumn']>(() => {
    return {
      width: 60,
      align: 'center',
      selectedRowKeys: selectedKeys,
      onChange: onSelect,
    };
  }, [selectedKeys, onSelect]);

  const columns = useMemo<TableProps['columns']>(
    () => [
      {
        title: '名称',
        dataIndex: 'name',
        key: 'name',
        render: (value, item) => (
          <div className="flex items-center gap-3">
            {item.type === 'image' && (
              <div className="avatar">
                <div className="mask mask-squircle size-12">
                  <IntersectionObserver
                    root={containerRef.current}
                    width={48}
                    height={48}
                    rootMargin="-20px"
                  >
                    {(isIntersecting) => {
                      if (!isIntersecting) return <div className="size-full bg-gray-300" />;
                      return (
                        <ImageView
                          src={item.imageUrl + '?w=48&h=48&format=webp'}
                          alt={item.description ?? item.name}
                          width={48}
                          height={48}
                        />
                      );
                    }}
                  </IntersectionObserver>
                </div>
              </div>
            )}
            {item.type === 'folder' && (
              <div className="size-12 grid place-items-center text-yellow-500">
                <FolderFilled className="text-4xl" />
              </div>
            )}
            <span className="font-bold">{value}</span>
          </div>
        ),
      },
      {
        title: '存储实例',
        dataIndex: 'storageSystem',
        key: 'storageSystem',
        width: 120,
        align: 'center',
        render: (value) => <span className="text-gray-500">{value || '-'}</span>,
      },
      {
        title: '访问',
        dataIndex: 'isPublic',
        key: 'isPublic',
        width: 100,
        align: 'center',
        render: (value, record) => {
          if (record.type === 'folder') {
            return <span className="text-gray-500">-</span>;
          }
          return <span className="text-gray-500">{value ? '公开' : '私有'}</span>;
        },
      },
      {
        title: '大小',
        dataIndex: 'fileSize',
        key: 'fileSize',
        width: 150,
        align: 'center',
        render: (value) => {
          const text = calculateFileSize(value);
          return <span className="text-gray-500">{text}</span>;
        },
      },
      {
        title: '创建时间',
        dataIndex: 'createdAt',
        width: 180,
        align: 'center',
        key: 'createdAt',
        render: (value) => <span className="text-gray-500">{value}</span>,
      },
      {
        title: '操作',
        key: 'actions',
        width: 120,
        align: 'center',
        render: (_, item) => (
          <div className="flex items-center justify-center gap-2">
            {item.type === 'image' && (
              <button
                type="button"
                className="btn btn-xs btn-circle tooltip tooltip-left [&:where([data-tip]):before]:text-xs [&:where([data-tip]):before]:font-normal"
                data-tip="复制链接"
                disabled={!item.isPublic}
                onClick={(e) => {
                  e.stopPropagation();
                  const url = new URL(item.imageUrl, window.location.origin);
                  copyToClipboard(url.href)
                    .then(() => {
                      toast.success('复制成功');
                    })
                    .catch(() => {
                      toast.error('复制失败');
                    });
                }}
              >
                <ChevronUpDownIcon className="size-4 rotate-90" />
              </button>
            )}
            {item.type === 'folder' && (
              <button
                type="button"
                className="btn btn-xs btn-circle tooltip tooltip-left [&:where([data-tip]):before]:text-xs [&:where([data-tip]):before]:font-normal"
                data-tip="下载"
                onClick={(e) => {
                  e.stopPropagation();
                }}
              >
                <ArrowDownTrayIcon className="size-3" />
              </button>
            )}
            <Dropdown
              className="btn btn-xs btn-circle tooltip tooltip-left [&:where([data-tip]):before]:text-xs [&:where([data-tip]):before]:font-normal"
              data-tip="更多"
              autoClose
              singleMode
              options={
                item.type === 'image'
                  ? [
                      {
                        label: '重命名',
                        value: 'rename',
                        icon: <IconRename className="size-4" />,
                      },
                      {
                        label: '编辑',
                        value: 'edit',
                        icon: <PencilSquareIcon className="size-4" />,
                      },
                      {
                        label: '删除',
                        value: 'delete',
                        icon: <TrashIcon className="size-4 !text-red-500" />,
                      },
                      {
                        type: 'divider',
                      },
                      {
                        label: '分享',
                        value: 'share',
                        icon: <ShareIcon className="size-4" />,
                        disabled: !item.isPublic,
                      },
                      {
                        label: '下载',
                        value: 'download',
                        icon: <ArrowDownTrayIcon className="size-4" />,
                      },
                    ]
                  : [
                      {
                        label: '编辑',
                        value: 'edit',
                        icon: <PencilSquareIcon className="size-4" />,
                        onClick: (option) => {
                          console.log('edit', option);
                        },
                      },
                      {
                        label: '删除',
                        value: 'delete',
                        icon: <TrashIcon className="size-4 !text-red-500" />,
                      },
                    ]
              }
            >
              <EllipsisVerticalIcon className="size-4" />
            </Dropdown>
          </div>
        ),
      },
    ],
    [calculateFileSize]
  );

  const isEmpty = !dataSource?.length;

  if (loading && isEmpty) {
    return (
      <div className={clsx('list [--border:0] w-full', className)}>
        {new Array(5).fill(0).map((_, index) => (
          <div className="list-row" key={index}>
            <div className="skeleton size-10" />
            <div className="skeleton w-full" />
          </div>
        ))}
      </div>
    );
  }

  if (isEmpty) {
    if (isSearchMode) {
      return (
        <div
          className={clsx(
            'relative size-full overflow-auto flex items-center justify-center',
            className
          )}
        >
          <div className="card bg-base-100 w-96">
            <figure>
              <Image
                src="/images/no_search_result.webp"
                alt="无搜索结果"
                width={0}
                height={0}
                sizes="100vw"
                className="w-full h-[180px] object-contain"
                unoptimized
                priority
              />
            </figure>
            <div className="card-body">
              <p className="text-gray-400">没有搜索出任何内容，您可以尝试更换关键词重试</p>
            </div>
          </div>
        </div>
      );
    }
    return (
      <div className={clsx('relative size-full overflow-auto', className)}>
        <div className="grid place-items-center size-full">
          <div className="w-64 bg-base-100 dark:bg-base-300 rounded-box shadow-[0px_0px_15px_rgba(0,0,0,0.09)] p-9 space-y-3 relative overflow-hidden">
            <div className="w-24 h-24 bg-violet-500 dark:bg-violet-700 rounded-full absolute -right-5 -top-7">
              <p className="absolute bottom-6 left-6 text-white text-lg">提示</p>
            </div>
            <div className="w-12">
              <CloudArrowUpIcon className="size-12 text-violet-500" />
            </div>
            <h1 className="font-bold text-xl">我的图库</h1>
            <p className="text-sm text-zinc-500 leading-6">
              当前目录没有任何图片或文件夹，您可以点击工具栏上传图片或创建文件夹。
            </p>
          </div>
        </div>
      </div>
    );
  }

  const isModePending = deferredMode !== mode;

  if (isModePending) {
    return (
      <div className="flex flex-col items-center justify-center gap-2 size-full min-h-20">
        <span className="loading loading-spinner" />
        <span className="text-sm text-gray-500">加载中...</span>
      </div>
    );
  }

  return (
    <div className={clsx('relative overflow-auto', className)} ref={containerRef}>
      {deferredMode === 'list' && (
        <Table
          tableClassName="min-w-4xl"
          rowKey="id"
          loading={loading}
          dataSource={dataSource}
          rowSelectionColumn={rowSelectionColumn}
          rowProps={rowProps}
          columns={columns}
        />
      )}
      {deferredMode === 'grid' && (
        <GridView
          selectedKeys={selectedKeys}
          dataSource={dataSource}
          root={containerRef.current}
          onSelect={onSelect}
          onClick={handleItemClick}
        />
      )}
      {loadingMore && (
        <div className="px-3 w-full">
          <div className="skeleton w-full h-5" />
        </div>
      )}
      {noMore && (
        <div className="flex items-center justify-center p-3">
          <span className="text-gray-500 text-xs">没有更多了</span>
        </div>
      )}
    </div>
  );
}

export const GalleryList = React.memo(GalleryListNoMemoized);
